package cn.tannn.ops.pwd.strategy.impl;

import cn.tannn.jdevelops.exception.built.BusinessException;
import cn.tannn.ops.initialize.Ip2regionInit;
import cn.tannn.ops.pwd.strategy.EncryptStrategy;
import lombok.SneakyThrows;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Base64;

import static cn.tannn.ops.util.RasUtil.loadPrivateKeyByStr;
import static cn.tannn.ops.util.RasUtil.loadPublicKeyByStr;


/**
 * RSA  加解密策略具体实现
 * @link <a href="https://developer.aliyun.com/article/1045740">参考</a>
 *
 * @author tnnn
 * @version V1.0
 * @date 2023-02-20 10:24
 */
public class EncryptStrategyRSA implements EncryptStrategy {

    private static final Logger LOGGER = LoggerFactory.getLogger(EncryptStrategyRSA.class);
    private final static String ALGORITHM_RSA = "RSA";
    private final static String CHARSET_NAME = "UTF-8";

    @SneakyThrows
    @Override
    public String encrypt(String secret, String content, Integer count) {
        return encrypt(content, secret);
    }


    @SneakyThrows
    @Override
    public String decrypt(String secret, String content, Integer count) {
        return decrypt(content, secret);
    }


    /**
     * RSA公钥加密
     * @param content 加密字符串
     * @param publicKey 公钥
     * @return 密文
     * @throws Exception Exception
     */
    public static String encrypt(String content,String publicKey) throws Exception {
        //公钥
        RSAPublicKey pubKey=  loadPublicKeyByStr(publicKey);
        try {
            //RSA加密
            Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            return Base64.getEncoder().encodeToString(cipher.doFinal(content.getBytes(CHARSET_NAME)));
        } catch (NoSuchAlgorithmException e) {
            throw new NoSuchAlgorithmException("无此加密算法",e);
        } catch (NoSuchPaddingException e) {
            LOGGER.error("无此加密Padding",e);
            return null;
        } catch (InvalidKeyException e) {
            throw new InvalidKeyException("加密私钥非法,请检查",e);
        } catch (IllegalBlockSizeException e) {
            throw new BusinessException("明文长度非法",e);
        } catch (BadPaddingException e) {
            throw new BusinessException("明文数据已损坏",e);
        }
    }




    /**
     * RSA私钥解密
     * @param content 加密字符串
     * @param privateKey 私钥
     * @return 明文
     * @throws Exception Exception
     */
    public static String decrypt(String content,String privateKey) throws Exception {
        // 私钥
        RSAPrivateKey priKey = loadPrivateKeyByStr(privateKey);
        try {
            //RSA解密
            byte[] inputByte = Base64.getDecoder().decode(content);
            Cipher cipher = Cipher.getInstance(ALGORITHM_RSA);
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            return new String(cipher.doFinal(inputByte));
        } catch (NoSuchAlgorithmException e) {
            throw new NoSuchAlgorithmException("无此解密算法",e);
        } catch (NoSuchPaddingException e) {
            LOGGER.error("无此加密Padding",e);
            return null;
        } catch (InvalidKeyException e) {
            throw new InvalidKeyException("解密私钥非法,请检查",e);
        } catch (IllegalBlockSizeException e) {
            throw new BusinessException("密文长度非法",e);
        } catch (BadPaddingException e) {
            throw new BusinessException("密文数据已损坏",e);
        }
    }


}
